`include "defines.v"
module ex_mem(
	input wire clk,
	input wire rst,
	input wire[31:0] write_data_i,
	input wire write_ce_i,
	input wire[4:0] write_addr_i,
	output reg[31:0] write_data_o,
	output reg write_ce_o,
	output reg[4:0] write_addr_o,
	
	//与hilo寄存器相关的数据
	input wire[31:0] hi_i,
	input wire[31:0] lo_i,
	input wire hilo_write_ce_i,
	output reg[31:0] hi_o,
	output reg[31:0] lo_o,
	output reg hilo_write_ce_o,
	input wire[5:0] pause, //流水线暂停信号

	input wire[63:0] hilo_temp_i, //乘法结果
	input wire[1:0] count_i, //下一个时钟周期是第几个执行周期
	output reg[63:0] hilo_temp_o, //乘法结果
	output reg[1:0] count_o, //当前时钟周期处于执行阶段的第几个周期
	
	//访存指令信号
	input wire[31:0] mem_addr_i,
	input wire[31:0] mem_wdata_i,
	input wire[`AluOpWidth-1:0] alu_op_i,
	output reg[31:0] mem_addr_o,
	output reg[31:0] mem_wdata_o,
	output reg[`AluOpWidth-1:0] alu_op_o,
	//CP0相关信号
	input wire[31:0] ex_cp0_wData_i,
	input wire[4:0] ex_cp0_wAddr_i,
	input wire ex_cp0_wCe_i,
	output reg[31:0] mem_cp0_wData_o,
	output reg[4:0] mem_cp0_wAddr_o,
	output reg mem_cp0_wCe_o,
	//异常相关
	input wire exception, //是否发生中断
	input wire[31:0] ex_exception_type_i, //异常类型
	input wire[31:0] ex_current_inst_addr_i, //当前执行指令的地址
	input wire ex_is_in_delaySlot_i, //执行阶段是否是延迟槽指令
	
	output reg[31:0] mem_exception_type_o, //异常类型
	output reg[31:0] mem_current_inst_addr_o, //当前访存阶段指令的地址
	output reg mem_is_in_delaySlot_o //访存阶段是否是延迟槽指令
);
	
	always@(posedge clk)
		if(rst == `RstEnable)
		begin
			hilo_temp_o <= {`ZeroWord, `ZeroWord};
			count_o <= 2'b00;
		end
		else if(exception == `Exception_Happen)
		begin
			hilo_temp_o <= {`ZeroWord, `ZeroWord};
			count_o <= 2'b00;
		end
		else if(pause[3] == `PAUSE && pause[4] == `NO_PAUSE) 
		begin
			hilo_temp_o <= hilo_temp_i;
			count_o <= count_i;
		end
		else 
		begin
			hilo_temp_o <= {`ZeroWord, `ZeroWord};
			count_o <= 2'b00;
		end
		
	always@(posedge clk) 
		if(rst == `RstEnable)
		begin
			write_data_o <= `ZeroWord;
			write_ce_o <= `WriteDisable;
 			write_addr_o <= 5'b00000;
			hi_o <= `ZeroWord;
			lo_o <= `ZeroWord;
			hilo_write_ce_o <= `WriteDisable;
			
			mem_addr_o <= `ZeroWord;
			mem_wdata_o <= `ZeroWord;
			alu_op_o <= `ALU_NOP_OP;
			
			mem_cp0_wData_o <= `ZeroWord;
			mem_cp0_wAddr_o <= 5'b00000;
			mem_cp0_wCe_o <= `WriteDisable;
			
			mem_exception_type_o <= `ZeroWord;
			mem_current_inst_addr_o <= `ZeroWord;
			mem_is_in_delaySlot_o <= `NotInDelaySlot;
		end
		else if((exception == `Exception_Happen) || (pause[3] == `PAUSE && pause[4] == `NO_PAUSE)) //执行阶段暂停，访存阶段继续
		begin
			write_data_o <= `ZeroWord;
			write_ce_o <= `WriteDisable;
 			write_addr_o <= 5'b00000;
			hi_o <= `ZeroWord;
			lo_o <= `ZeroWord;
			hilo_write_ce_o <= `WriteDisable;
			
			mem_addr_o <= `ZeroWord;
			mem_wdata_o <= `ZeroWord;
			alu_op_o <= `ALU_NOP_OP;
			
			mem_cp0_wData_o <= `ZeroWord;
			mem_cp0_wAddr_o <= 5'b00000;
			mem_cp0_wCe_o <= `WriteDisable;
			
			mem_exception_type_o <= `ZeroWord;
			mem_current_inst_addr_o <= `ZeroWord;
			mem_is_in_delaySlot_o <= `NotInDelaySlot;
		end
		else if(pause[3] == `NO_PAUSE)
		begin
			write_data_o <= write_data_i;
			write_ce_o <= write_ce_i;
 			write_addr_o <= write_addr_i;
			hi_o <= hi_i;
			lo_o <= lo_i;
			hilo_write_ce_o <= hilo_write_ce_i;
			
			mem_addr_o <= mem_addr_i;
			mem_wdata_o <= mem_wdata_i;
			alu_op_o <= alu_op_i;
			
			mem_cp0_wData_o <= ex_cp0_wData_i;
			mem_cp0_wAddr_o <= ex_cp0_wAddr_i;
			mem_cp0_wCe_o <= ex_cp0_wCe_i;
			
			mem_exception_type_o <= ex_exception_type_i;
			mem_current_inst_addr_o <= ex_current_inst_addr_i;
			mem_is_in_delaySlot_o <= ex_is_in_delaySlot_i;
		end

endmodule
